home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / misc / gnuplot-3.7src.lha / gnuplot-3.7src / gnuplot-3.7.lha / gnuplot-3.7 / alloc.c < prev    next >
C/C++ Source or Header  |  1998-04-15  |  9KB  |  350 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: alloc.c,v 1.12 1998/03/22 22:31:16 drd Exp $";
  3. #endif
  4.  
  5. /* GNUPLOT - alloc.c */
  6.  
  7. /*[
  8.  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted,
  12.  * provided that the above copyright notice appear in all copies and
  13.  * that both that copyright notice and this permission notice appear
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the complete modified source code.  Modifications are to
  18.  * be distributed as patches to the released version.  Permission to
  19.  * distribute binaries produced by compiling modified sources is granted,
  20.  * provided you
  21.  *   1. distribute the corresponding source modifications from the
  22.  *    released version in the form of a patch file along with the binaries,
  23.  *   2. add special version identification to distinguish your version
  24.  *    in addition to the base release version number,
  25.  *   3. provide your name and address as the primary contact for the
  26.  *    support of your modified version, and
  27.  *   4. retain our contact information in regard to use of the base
  28.  *    software.
  29.  * Permission to distribute the released version of the source code along
  30.  * with corresponding source modifications in the form of a patch file is
  31.  * granted with same provisions 2 through 4 for binary distributions.
  32.  *
  33.  * This software is provided "as is" without express or implied warranty
  34.  * to the extent permitted by applicable law.
  35. ]*/
  36.  
  37. /*
  38.  * AUTHORS
  39.  *
  40.  * Alexander Lehmann (collected functions from misc.c and binary.c)
  41.  *
  42.  */
  43.  
  44. #include "plot.h" /* includes "alloc.h" */
  45.  
  46. #if defined(MSDOS) && defined(__TURBOC__) && !defined(DOSX286)
  47. #include <alloc.h>        /* for farmalloc, farrealloc */
  48. #endif
  49.  
  50. #if defined(_Windows) && !defined(WIN32)
  51. #include <windows.h>
  52. #include <windowsx.h>
  53. #define farmalloc(s) GlobalAllocPtr(GHND,s)
  54. #define farrealloc(p,s) GlobalReAllocPtr(p,s,GHND)
  55. #endif
  56.  
  57. #ifndef NO_GIH
  58. #include "help.h"
  59. #endif
  60.  
  61. #ifndef GP_FARMALLOC
  62. # ifdef FARALLOC
  63. #  define GP_FARMALLOC(size) farmalloc ((size))
  64. #  define GP_FARREALLOC(p,size) farrealloc ((p), (size))
  65. # else
  66. #  define GP_FARMALLOC(size) malloc ((size_t)(size))
  67. #  define GP_FARREALLOC(p,size) realloc ((p), (size_t)(size))
  68. # endif
  69. #endif
  70.  
  71. /* uncomment if you want to trace all allocs */
  72. #define TRACE_ALLOC(x) /*printf x*/
  73.  
  74.  
  75. #ifdef CHECK_HEAP_USE
  76.  
  77. /* This is in no way supported, and in particular it breaks the
  78.  * online help. But it is useful to leave it in in case any
  79.  * heap-corruption bugs turn up. Wont work with FARALLOC
  80.  */
  81.  
  82. struct frame_struct {
  83.     char *use;
  84.     int requested_size;
  85.     int pad; /* preserve 8-byte alignment */
  86.     int checksum;
  87. };
  88.  
  89. struct leak_struct {
  90.     char *file;
  91.     int line;
  92.     int allocated;
  93. };
  94.  
  95. static struct leak_struct leak_stack[40];  /* up to 40 nested leak checks */
  96. static struct leak_struct *leak_frame = leak_stack;
  97.  
  98. static long bytes_allocated = 0;
  99.  
  100. #define RESERVED_SIZE sizeof(struct frame_struct)
  101. #define CHECKSUM_INT 0xcaac5e1f
  102. #define CHECKSUM_FREE 0xf3eed222
  103. #define CHECKSUM_CHAR 0xc5
  104.  
  105. static void mark(p, size, usage)
  106. struct frame_struct *p;
  107. unsigned long size;
  108. char *usage;
  109. {
  110.     p->use = usage;
  111.     p->requested_size = size;
  112.     p->checksum = (CHECKSUM_INT ^ (int)(p->use) ^ size);
  113.     ((unsigned char *)(p+1))[size] = CHECKSUM_CHAR;
  114. }
  115.  
  116. #define mark_free(p) ( ((struct frame_struct *)p)[-1].checksum = CHECKSUM_FREE)
  117.     
  118. static void validate(x)
  119. void *x;
  120. {
  121.     struct frame_struct *p = (struct frame_struct *)x - 1;
  122.     if (p->checksum != (CHECKSUM_INT ^ (int)(p->use) ^ p->requested_size))
  123.     {
  124.         fprintf(stderr, "Heap corruption at start of block for %s\n", p->use);
  125.         if (p->checksum == CHECKSUM_FREE)
  126.             fprintf(stderr, "Looks like it has already been freed ?\n");
  127.         abort();
  128.     }
  129.  
  130.     if ( ((unsigned char *)(p+1))[p->requested_size] != CHECKSUM_CHAR)
  131.     {
  132.         fprintf(stderr, "Heap corruption at end of block for %-60s\n", p->use);
  133.         int_error("Argh !", NO_CARET);
  134.     }
  135. }        
  136.  
  137. /* used to confirm that a pointer is inside an allocated region via
  138.  * macro CHECK_POINTER. Nowhere near as good as using a bounds-checking
  139.  * compiler (such as gcc-with-bounds-checking), but when we do
  140.  * come across problems, we can add these guards to the code until
  141.  * we find the problem, and then leave the guards in (as CHECK_POINTER
  142.  * macros which expand to nothing, until we need to re-enable them)
  143.  */
  144.  
  145. void check_pointer_in_block(void *block, void *p, int size, char *file, int line)
  146. {
  147.     struct frame_struct *f = (struct frame_struct *)block - 1;
  148.     validate(block);
  149.     if (p < block || p >= (block + f->requested_size))
  150.     {
  151.         fprintf(stderr, "argh - pointer %p outside block %p->%p for %s at %s:%d\n",
  152.           p, block, (char *)block + f->requested_size, f->use, file, line);
  153.         int_error("argh - pointer misuse !", NO_CARET);
  154.     }
  155. }
  156.  
  157. char *gp_alloc(size, usage)
  158. unsigned long size;
  159. char *usage;
  160. {
  161.     struct frame_struct *p;
  162.     unsigned long total_size = size + RESERVED_SIZE + 1;
  163.     
  164.     TRACE_ALLOC(("gp_alloc %d for %s\n", (int) size, usage?usage:"<unknown>"));
  165.     
  166.     p=malloc(total_size);
  167.     if (!p) int_error("Out of memory", NO_CARET);
  168.  
  169.     bytes_allocated += size;
  170.     
  171.     mark(p,size,usage);
  172.     
  173.     return (char *)(p+1);
  174. }
  175.  
  176. generic *gp_realloc(old, size, usage)
  177. generic *old;
  178. unsigned long size;
  179. char *usage;
  180. {
  181.     if (!old) return gp_alloc(size, usage);
  182.     validate(old);
  183.     mark_free(old); /* if block gets moved, old block is marked free */
  184.                     /* if not, we'll remark it later */
  185.  
  186.     
  187.     {
  188.         struct frame_struct *p = (struct frame_struct *)old - 1;
  189.         unsigned long total = size + RESERVED_SIZE + 1;
  190.  
  191.         p = realloc(p, total);
  192.  
  193.         if (!p) int_error("Out of memory", NO_CARET);
  194.  
  195.         TRACE_ALLOC(("gp_realloc %d for %s (was %d)\n",
  196.           (int)size, usage?usage:"<unknown>", p->requested_size));
  197.  
  198.         bytes_allocated += size - p->requested_size;
  199.         
  200.         mark(p,size,usage);
  201.  
  202.         return (generic *)(p+1);
  203.     }
  204. }
  205.  
  206. #undef free
  207.  
  208. void checked_free(p)
  209. void *p;
  210. {
  211.     validate(p);
  212.     mark_free(p);  /* trap attempts to free twice */
  213.     TRACE_ALLOC(("free %d for %s\n",
  214.       ((struct frame_struct *)p - 1)->requested_size,
  215.       ((struct frame_struct *)p - 1)->use));
  216.     bytes_allocated -= ((struct frame_struct *)p - 1) -> requested_size;
  217.     free( (struct frame_struct *) p - 1);
  218. }
  219.  
  220.  
  221. /* this leak checking stuff will be broken by first int_error or interrupt */
  222.  
  223. void start_leak_check(char *file, int line)
  224. {
  225.     if (leak_frame >= leak_stack+40)
  226.     {
  227.         fprintf(stderr, "too many nested memory-leak checks - %s:%d\n", file, line);
  228.         return;
  229.     }
  230.  
  231.     leak_frame->file = file;
  232.     leak_frame->line = line;
  233.     leak_frame->allocated = bytes_allocated;
  234.  
  235.     ++leak_frame;
  236. }
  237.  
  238. void end_leak_check(char *file, int line)
  239. {
  240.     if (--leak_frame < leak_stack)
  241.     {
  242.         fprintf(stderr, "memory-leak stack underflow at %s:%d\n", file, line);
  243.         return;
  244.     }
  245.  
  246.     if (leak_frame->allocated != bytes_allocated)
  247.     {
  248.         fprintf(stderr, "net change of %+d heap bytes between %s:%d and %s:%d\n",
  249.             (int)(bytes_allocated - leak_frame->allocated),
  250.             leak_frame->file, leak_frame->line, file, line);
  251.     }
  252. }
  253.  
  254. #else  /* CHECK_HEAP_USE */
  255.  
  256. /* gp_alloc:
  257.  * allocate memory 
  258.  * This is a protected version of malloc. It causes an int_error 
  259.  * if there is not enough memory, but first it tries FreeHelp() 
  260.  * to make some room, and tries again. If message is NULL, we 
  261.  * allow NULL return. Otherwise, we handle the error, using the
  262.  * message to create the int_error string. Note cp/sp_extend uses realloc,
  263.  * so it depends on this using malloc().
  264.  */
  265.  
  266. char *
  267. gp_alloc(size, message)
  268.     unsigned long size;        /* # of bytes */
  269.     char *message;            /* description of what is being allocated */
  270. {
  271.     char *p;                /* the new allocation */
  272.     char errbuf[100];        /* error message string */
  273.  
  274. #ifndef NO_GIH
  275.     p = GP_FARMALLOC(size);
  276.     if (p == (char *)NULL) {
  277.        FreeHelp();            /* out of memory, try to make some room */
  278. #endif /* NO_GIH */
  279.        p = GP_FARMALLOC(size);    /* try again */
  280.        if (p == (char *)NULL) {
  281.           /* really out of memory */
  282.           if (message != NULL) {
  283.              (void) sprintf(errbuf, "out of memory for %s", message);
  284.              int_error(errbuf, NO_CARET);
  285.              /* NOTREACHED */
  286.           }
  287.           /* else we return NULL */
  288.        }
  289. #ifndef NO_GIH
  290.     }
  291. #endif
  292.     return(p);
  293. }
  294.  
  295. /*
  296.  * note gp_realloc assumes that failed realloc calls leave the original mem block
  297.  * allocated. If this is not the case with any C compiler, a substitue
  298.  * realloc function has to be used.
  299.  */
  300.  
  301. generic *
  302. gp_realloc(p, size, message)
  303.     generic *p;            /* old mem block */
  304.     unsigned long size;        /* # of bytes */
  305.     char *message;            /* description of what is being allocated */
  306. {
  307.     char *res;                /* the new allocation */
  308.     char errbuf[100];        /* error message string */
  309.  
  310.     /* realloc(NULL,x) is meant to do malloc(x), but doesn't always */
  311.     if (!p)
  312.     return gp_alloc(size,message);
  313.  
  314. #ifndef NO_GIH
  315.     res = GP_FARREALLOC(p,size);
  316.     if (res == (char *)NULL) {
  317.        FreeHelp();            /* out of memory, try to make some room */
  318. #endif /* NO_GIH */
  319.        res = GP_FARREALLOC(p,size);    /* try again */
  320.        if (res == (char *)NULL) {
  321.           /* really out of memory */
  322.           if (message != NULL) {
  323.              (void) sprintf(errbuf, "out of memory for %s", message);
  324.              int_error(errbuf, NO_CARET);
  325.              /* NOTREACHED */
  326.           }
  327.           /* else we return NULL */
  328.        }
  329. #ifndef NO_GIH
  330.     }
  331. #endif
  332.     return(res);
  333. }
  334.  
  335. #endif /* CHECK_HEAP_USE */
  336.  
  337. #ifdef FARALLOC
  338. void gpfree(p)
  339. generic *p;
  340. {
  341. #ifdef _Windows
  342. HGLOBAL hGlobal = GlobalHandle(SELECTOROF(p));
  343.     GlobalUnlock(hGlobal);
  344.     GlobalFree(hGlobal);
  345. #else
  346.     farfree(p);
  347. #endif
  348. }
  349. #endif
  350.